#include "loader.h"
#include "mmu.h"
#include "tss.h"
#include "klib.h"
#include "gdt.h"
#include "i386.h"

void cargar_tarea_inicial(){
	unsigned int base = (unsigned int)&tsss[0];
	unsigned int base_0_15 = base & 0x0000FFFF;
	unsigned int base_16_23 = (base & 0x00FF0000) >> 16;
	unsigned int base_24_31 = (base >> 24) & 0x000000FF;
	
	gdt_entry entrada = {0x0067,base_0_15,base_16_23,0x9,0x0,0x0,0x1,0x0,0x0,0x0,0x1,0x0,base_24_31};
	nueva_entrada_gdt(entrada);		
}	


void cargar_tarea(unsigned int desde, unsigned int indice) {  //indice=0 <-> tarea 0 .. desde=0x10.000 <-> indice=1(tarea 1) .. 0x12.000 <-> indice=2(tarea 2) ....
	
	// Creamos el directorio y la tabla de paginas con 1mb de identity mapping.
	unsigned int* dir_user = inicializar_dir_usuario(); //va a ser el cr3.
	
	// obtenemos 2 paginas de usuario para los 8kb de codigos+datos de la tarea.
	unsigned int* pag_codigo_1 = pagina_libre_usuario();
	unsigned int* pag_codigo_2 = pagina_libre_usuario(); 
	
	// Las llenamos con los 8kb a partir de desde.
	unsigned int* ptr_fuente = (unsigned int*)desde;
	unsigned int* ptr_destino = pag_codigo_1;
	int i;
	for(i=0;i<2048;i++){ //	2048 = 8kb/4 (porque el ptr avanza de a 4 bytes).
		ptr_destino[i] = ptr_fuente[i]; 
	}
	
	// obtenemos pagina de usuario para la pila de anillo 3.
	unsigned int* pag_user_pila = pagina_libre_usuario();

	// obtenemos pagina de kernel para la pila de anillo 0.	
	unsigned int* pag_kernel_pila =	pagina_libre_kernel();
	
	unsigned int atributos_kernel = 0x3; 	//supervisor
	unsigned int atributos_user = 0x7;		//usuario
	
	
	// Mapeamos las paginas de las pilas de usuario y kernel.
	mapear_pagina((unsigned int)pag_user_pila ,(unsigned int) dir_user,(unsigned int)pag_user_pila,(unsigned int)atributos_user);
	mapear_pagina((unsigned int)pag_kernel_pila,(unsigned int) dir_user,(unsigned int)pag_kernel_pila,(unsigned int)atributos_kernel);
	
	// Mapeamos las paginas del codigo+datos de la tarea.
	mapear_pagina((unsigned int)0x0000,(unsigned int)dir_user,(unsigned int)pag_codigo_1,(unsigned int)atributos_user);	
	mapear_pagina((unsigned int)0x1000,(unsigned int)dir_user,(unsigned int)pag_codigo_2,(unsigned int)atributos_user);	
	
	// Cargamos la tss.
	
	tsss[indice].ptl = 0x0000;		
	tsss[indice].unused0 = 0x0000;
	tsss[indice].esp0 = (unsigned int)pag_kernel_pila + 4096;
	tsss[indice].ss0 = 0x0010;
	tsss[indice].unused1 = 0x0000;
	tsss[indice].esp1 = 0x00000000;
	tsss[indice].ss1 = 0x0000;
	tsss[indice].unused2 = 0x0000;
	tsss[indice].esp2 = 0x00000000;
	tsss[indice].ss2 = 0x0000;
	tsss[indice].unused3 = 0x0000;
	tsss[indice].cr3 = (unsigned int)dir_user;
	tsss[indice].eip = 0x0; // Direccion del codigo virtual.
	tsss[indice].eflags = 0x00000202;
	tsss[indice].eax = 0x00000000;
	tsss[indice].ecx = 0x00000000;
	tsss[indice].edx = 0x00000000;
	tsss[indice].ebx = 0x00000000;
	tsss[indice].esp = (unsigned int)pag_user_pila + 4096;
	tsss[indice].ebp = (unsigned int)pag_user_pila + 4096;
	tsss[indice].esi = 0x00000000;
	tsss[indice].edi = 0x00000000;
	tsss[indice].es = 0x002B;
	tsss[indice].unused4 = 0x0000;
	tsss[indice].cs = 0x0023;
	tsss[indice].unused5 = 0x0000;
	tsss[indice].ss = 0x002B;
	tsss[indice].unused6 = 0x0000;
	tsss[indice].ds = 0x002B;
	tsss[indice].unused7 = 0x0000;
	tsss[indice].fs = 0x002B;
	tsss[indice].unused8 = 0x0000;
	tsss[indice].gs = 0x002B;
	tsss[indice].unused9 = 0x0000;
	tsss[indice].ldt = 0x0000;
	tsss[indice].unused10 = 0x0000;
	tsss[indice].dtrap = 0x0010;
	tsss[indice].iomap = 0xFE00;
	
		
	unsigned int base = (unsigned int)&tsss[indice];
	unsigned int base_0_15 = base & 0x0000FFFF;
	unsigned int base_16_23 = (base & 0x00FF0000) >> 16;
	unsigned int base_24_31 = (base >> 24) & 0x000000FF;
	
	gdt_entry entrada = {0x0067,base_0_15,base_16_23,0x9,0x0,0x0,0x1,0x0,0x0,0x0,0x1,0x0,base_24_31};
	nueva_entrada_gdt(entrada);		
}
